/**
 * Copyright (c) Chris Myers 2007
 * Aug 11, 2007
 */
package com.chrisandjo.rostra.service;

import com.chrisandjo.rostra.dao.PersonDao;
import com.chrisandjo.rostra.dao.RosterDao;
import com.chrisandjo.rostra.domain.Person;
import com.chrisandjo.rostra.domain.Roster;
import com.chrisandjo.rostra.domain.RosterEntity;
import static com.googlecode.instinct.expect.Expect.expect;
import com.googlecode.instinct.integrate.junit4.InstinctRunner;
import com.googlecode.instinct.marker.annotate.BeforeSpecification;
import com.googlecode.instinct.marker.annotate.Dummy;
import com.googlecode.instinct.marker.annotate.Mock;
import com.googlecode.instinct.marker.annotate.Specification;
import org.jmock.Expectations;
import org.junit.runner.RunWith;

import java.util.List;
import java.util.Set;


/**
 * @author Chris
 */
@SuppressWarnings({"UnusedDeclaration"})
@RunWith(InstinctRunner.class)
public class ARosterService {
    private RosterService service;
    private Roster roster;
    @Mock private Person person;
    @Mock private PersonDao personDao;
    @Mock private RosterDao rosterDao;
    @Dummy private List<Roster> rosters;
    @Dummy private Set<Person> people;

    @BeforeSpecification
    public void setUp() throws Exception {
        service = new RosterServiceImpl(rosterDao, personDao);
        roster = new RosterEntity("creche");
        roster.addPerson(person);
    }

    @Specification
    public void createsANewRosterWithAName() {
        String name = "test";
        createRoster(name + "abc");
        createRoster(name + "xyz");
    }

    @SuppressWarnings({"ThrowableInstanceNeverThrown"})
    @Specification(expectedException = IllegalArgumentException.class)
    public void throwsExceptionWhenARosterIsCreatedWithAnExistingName() {
        expect.that(new Expectations() {
            {
                one(rosterDao).rosterExists("test");
                will(returnValue(false));
                one(rosterDao).save(with(any(Roster.class)));
                one(rosterDao).rosterExists("test");
                will(returnValue(true));
            }
        });
        service.createNewRoster("test");
        service.createNewRoster("test");
    }

    @Specification
    public void mustReturnThePeopleOnARoster() {
        expect.that(new Expectations() {
            {
                one(rosterDao).getRosterById(1);
                will(returnValue(roster));
            }
        });
        expect.that(service.getPeopleOnRoster(1)).containsItem(person);
    }

    @Specification
    public void mustAddAPersonToRoster() {
        expect.that(new Expectations() {
            {
                one(personDao).getPersonById(1);
                will(returnValue(person));
                one(rosterDao).getRosterById(1);
                will(returnValue(roster));
                one(rosterDao).save(roster);
            }
        });
        service.addPersonToRoster(1, 1);
        expect.that(roster.getPeople()).containsItem(person);
    }

    @Specification
    public void mustRetrieveAListOfAllTheRostersWhenGetRostersIsCalled() {
        expect.that(new Expectations() {
            {
                one(rosterDao).getRosters();
                will(returnValue(rosters));
            }
        });
        expect.that(service.getRosters()).isEqualTo(rosters);
    }

    @Specification
    public void mustRetrieveAListOfAllPeopleWhenGetPeopleIsCalled() {
        expect.that(new Expectations() {
            {
                one(personDao).getPeople();
                will(returnValue(people));
            }
        });
        expect.that(service.getPeople()).isEqualTo(people);
    }

    private void createRoster(final String name) {
        expect.that(new Expectations() {
            {
                one(rosterDao).rosterExists(name);
                will(returnValue(false));
                one(rosterDao).save(with(any(Roster.class)));
            }
        });
        Roster roster = service.createNewRoster(name);
        expect.that(roster.getName()).isEqualTo(name);
    }

    @Specification
    public void mustCreateAPersonAndPersistIt() {
        expect.that(new Expectations() {
            {
                one(personDao).save(with(any(Person.class)));
            }
        });
        Person person = service.createNewPerson("Chris Myers");
        expect.that(person.getName()).isEqualTo("Chris Myers");
    }
}
